using System;
using System.Web;
using System.Web.SessionState;
using System.Web.Security;
using System.Text.RegularExpressions;

using Impact.Infrastructure.Exceptions;
using Impact.Infrastructure.State;
using Impact.Infrastructure.Logging;

namespace Impact.Web.Foundation.Handlers
{
    /// <summary>
    /// ImpactModule is an HttpModule for handling incoming requests for pages in the impact system.
    /// This module is responsible for function such as Url rewriting and validation, and any other
    /// request-level functions.
    /// </summary>
    public class ImpactModule : IHttpModule
    {

        #region IHttpModule Members

        /// <summary>
        /// sign up for the events we want to handle
        /// </summary>
        /// <param name="context"></param>
        public void Init(HttpApplication context)
        {
            //context.BeginRequest += new EventHandler(ForwardDefaultRequest);
            context.BeginRequest += new EventHandler(RedirectSubdomain);
            context.BeginRequest += new EventHandler(MaintenanceCheck);

            context.AcquireRequestState += new EventHandler(AcquireRequestState);
        }

        /// <summary>
        /// get rid of any resources we've used
        /// </summary>
        public void Dispose()
        {
        }

        #endregion


        /// <summary>
        /// checks for requests to the www subdomain and forwards them to the regular domain
        /// </summary>
        private void RedirectSubdomain(object sender, EventArgs e)
        {
            try
            {
                HttpContext context = HttpContext.Current;
                if (context.Request.PhysicalPath.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase)
                    || context.Request.PhysicalPath.EndsWith(".ashx", StringComparison.OrdinalIgnoreCase))
                {
                    string url = context.Request.Url.ToString();
                    if (regex.IsMatch(url))
                    {
                        url = regex.Replace(url, "$1://");
                        context.Response.StatusCode = 301; // moved permanently
                        context.Response.Redirect(url, false);
                    }
                }
            }
            catch (Exception ex)
            {
                ExceptionManager.Handle(ex);
            }
        }
        private static Regex regex = new Regex("(http|https)://www\\.", RegexOptions.IgnoreCase | RegexOptions.Compiled);


        /// <summary>
        /// check for any url rewrites that might be necessary
        /// </summary>
        private void ForwardDefaultRequest(object sender, EventArgs e)
        {

            try
            {
                string defaultDocument = "~/default.aspx";
                string requestPath = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.ToLower();
                if (requestPath.Equals(defaultDocument))
                {
                    // handle default document so the handler will pick it up
                    HttpContext.Current.RewritePath("~/default.ashx");
                }
            }
            catch (Exception ex)
            {
                ExceptionManager.Handle(ex);
            }

        }

        /// <summary>
        /// event handler is called when the state of this request has been instantiated
        /// </summary>
        private void AcquireRequestState(object sender, EventArgs e)
        {
            try
            {

                if (ProcessRequest())
                {
                    CreateTransaction();
                }
            }
            catch (Exception ex)
            {
                ExceptionManager.Handle(ex);
            }

        }


        private void MaintenanceCheck(object sender, EventArgs e)
        {
            Maintenance.Check();
        }


        #region Private Helpers

        /// <summary>
        /// creates a transaction for the current thread, and stores a sessionId to uniquely identify
        /// the session.
        /// </summary>
        private static void CreateTransaction()
        {
            HttpSessionState session = HttpContext.Current.Session;
            string sessionId;
            if (session != null)
            {
                if (session["sessionId"] != null)
                {
                    sessionId = (string)session["sessionId"];
                }
                else
                {
                    sessionId = Guid.NewGuid().ToString();
                    session["sessionId"] = sessionId;
                }
                Transaction t = new Transaction();
                t.SessionId = sessionId;

                MembershipUser user = Membership.GetUser();
                if (user != null)
                {
                    t.UserId = (Guid?)user.ProviderUserKey;
                }

                Transaction.Set(t);

            }

        }

        /// <summary>
        /// filter out requests we don't care about
        /// </summary>
        /// <returns>true if the request should be processed</returns>
        private bool ProcessRequest()
        {
            string url = HttpContext.Current.Request.Url.LocalPath;
            if (url.Contains(".aspx") || url.Contains(".ashx"))
                return true;

            else return false;
        }

        #endregion


    }
}
